﻿using System;
using System.Collections.Generic;
using System.Net;

namespace Com.ZGH.Dns
{
    public class DnsPacket : IElement
    {
        protected short packetId;
        protected short flags;
        protected short questionCount;
        protected short resourceCount;
        protected short authorizedResouceCount;
        protected short addtionalResourceCount;

        protected List<DnsQuestion> questions;
        protected List<DnsAnswer> answers;
        protected List<DnsAnswer> authorizedResources;
        protected List<DnsAnswer> addtionalResources;

        public short PacketId
        {
            get { return packetId; }
            set { packetId = value; }
        }

        public short Flags
        {
            get { return flags; }
            set { flags = value; }
        }

        public List<DnsQuestion> Questions
        {
            get { return questions; }
        }

        public List<DnsAnswer> Answers
        {
            get { return answers; }
        }

        public List<DnsAnswer> AuthorizedResources
        {
            get { return authorizedResources; }
        }

        public List<DnsAnswer> AddtionalResources
        {
            get { return addtionalResources; }
        }

        public DnsPacket()
        {
            questions=new List<DnsQuestion>();
            answers=new List<DnsAnswer>();
            authorizedResources=new List<DnsAnswer>();
            addtionalResources=new List<DnsAnswer>();
        }

        public void AddQuestion(DnsQuestion question)
        {
            questions.Add(question);
            questionCount++;
        }

        public void AddAnswer(DnsAnswer answer)
        {
            answers.Add(answer);
            resourceCount++;
        }

        public void AddAuthorizedResources(DnsAnswer answer)
        {
            authorizedResources.Add(answer);
            authorizedResouceCount++;
        }

        public void AddAddtionalResources(DnsAnswer answer)
        {
            addtionalResources.Add(answer);
            addtionalResourceCount++;
        }

        public int Size
        {
            get { throw new NotImplementedException(); }
        }

        public byte[] ToBytes()
        {
            var bytes = new List<byte>();

            bytes.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(packetId)));

            bytes.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(flags)));

            bytes.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(questionCount)));

            bytes.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(resourceCount)));

            bytes.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(authorizedResouceCount)));

            bytes.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(addtionalResourceCount)));

            foreach (var question in questions)
            {
                bytes.AddRange(question.ToBytes());
            }

            foreach (var dnsAnswer in answers)
            {
                bytes.AddRange(dnsAnswer.ToBytes());
            }

            foreach (var authorizedResource in authorizedResources)
            {
                bytes.AddRange(authorizedResource.ToBytes());
            }

            foreach (var addtionalResource in addtionalResources)
            {
                bytes.AddRange(addtionalResource.ToBytes());
            }

            return bytes.ToArray();
        }

        public static DnsPacket Parse(byte[] value)
        {
            var dnsPacket=new DnsPacket();

            dnsPacket.packetId = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(value, 0));

            dnsPacket.flags = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(value, 2));

            dnsPacket.questionCount = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(value, 4));

            dnsPacket.resourceCount = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(value, 6));

            dnsPacket.authorizedResouceCount = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(value, 8));

            dnsPacket.addtionalResourceCount = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(value, 10));

            var currentPos = 12;
            
            for (var i = 0; i < dnsPacket.questionCount; i++)
            {
                var x=DnsQuestion.Parse(value, currentPos);
                dnsPacket.questions.Add(x);
                currentPos += x.Size;
            }

            for (var i = 0; i < dnsPacket.resourceCount; i++)
            {

                var x = DnsAnswer.Parse(value, currentPos);
                dnsPacket.answers.Add(x);
                currentPos += x.Size;
            }

            for (var i = 0; i < dnsPacket.authorizedResouceCount; i++)
            {

                var x = DnsAnswer.Parse(value, currentPos);
                dnsPacket.authorizedResources.Add(x);
                currentPos += x.Size;
            }

            for (var i = 0; i < dnsPacket.addtionalResourceCount; i++)
            {
                var x = DnsAnswer.Parse(value, currentPos);
                dnsPacket.addtionalResources.Add(x);
                currentPos += x.Size;
            }

            return dnsPacket;
        }
    }
}
